package com.hanter.downloader;

import android.os.Handler;
import android.os.Looper;

import androidx.annotation.NonNull;

import com.hanter.downloader.exception.ResponseException;

public class ResponseDelivery implements Delivery {

    private final Handler handler;

    public ResponseDelivery() {
        this.handler = new Handler(Looper.getMainLooper());
    }

    @Override
    public void postProgress(@NonNull final Downloader.Request request, final long progress, final long max) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                RequestListener listener = request.getListener();
                if (listener != null) {
                    listener.onProgress(progress, max);
                }
            }
        });
    }

    @Override
    public void postComplete(@NonNull Downloader.Request request) {
        handler.post(new DeliveryRunnable(request, new Response(200)));
    }

    @Override
    public void postError(@NonNull Downloader.Request request, Response res) {
        handler.post(new DeliveryRunnable(request, res));
    }

    @Override
    public void postError(@NonNull Downloader.Request request, int err, String message) {
        handler.post(new DeliveryRunnable(request, new Response(err, message)));
    }

    @Override
    public void postCancel(@NonNull Downloader.Request request) {
        handler.post(new DeliveryRunnable(request, new Response(Response.ERROR_CANCELED)));
    }

    static class DeliveryRunnable implements Runnable {

        @NonNull
        private final Downloader.Request request;
        @NonNull
        private final Response res;

        DeliveryRunnable(@NonNull Downloader.Request request, @NonNull Response e) {
            this.request = request;
            this.res = e;
        }

        @Override
        public void run() {
            if (this.request.isCanceled() || this.res.isCanceled()) {
                deliveryCancel();
            } else if (this.res.getCode() == 200) {
                deliveryResponse();
            } else {
                deliveryError();
            }

            deliveryFinish();
        }

        private void deliveryCancel() {
            this.request.cancel();
            RequestListener listener = this.request.getListener();
            if (listener != null) {
                listener.onCancel();
            }
        }

        private void deliveryResponse() {
            this.request.success();
            RequestListener listener = this.request.getListener();
            if (listener != null) {
                listener.onResponse(this.request.getFilePath());
            }
        }

        private void deliveryError() {
            this.request.fail();
            RequestListener listener = this.request.getListener();
            if (listener != null) {
                listener.onError(new ResponseException(res));
            }
        }

        private void deliveryFinish() {
            RequestListener listener = this.request.getListener();
            if (listener != null) {
                listener.onFinish();
            }
        }
    }

}
